home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / libtiff / tif_packbits.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  250 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_packbits.c,v 1.29 92/10/26 17:08:54 sam Rel $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * PackBits Compression Algorithm Support
  33.  */
  34. #include "tiffiop.h"
  35.  
  36. #include <assert.h>
  37. #include <stdio.h>
  38.  
  39. static int
  40. DECLARE1(PackBitsPreEncode, TIFF*, tif)
  41. {
  42.     /*
  43.      * Calculate the scanline/tile-width size in bytes.
  44.      */
  45.     if (isTiled(tif))
  46.         tif->tif_data = (char *) TIFFTileRowSize(tif);
  47.     else
  48.         tif->tif_data = (char *) TIFFScanlineSize(tif);
  49.     return (1);
  50. }
  51.  
  52. /*
  53.  * Encode a run of pixels.
  54.  */
  55. static int
  56. DECLARE4(PackBitsEncode, TIFF*, tif, u_char*, bp, register u_long, cc, u_int, s)
  57. {
  58.     register char *op, *lastliteral;
  59.     register int n, b;
  60.     enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
  61.     char *ep;
  62.     int slop;
  63.  
  64.     op = tif->tif_rawcp;
  65.     ep = tif->tif_rawdata + tif->tif_rawdatasize;
  66.     state = BASE;
  67.     lastliteral = 0;
  68.     while (cc > 0) {
  69.         /*
  70.          * Find the longest string of identical bytes.
  71.          */
  72.         b = *bp++, cc--, n = 1;
  73.         for (; cc > 0 && b == *bp; cc--, bp++)
  74.             n++;
  75.     again:
  76.         if (op + 2 >= ep) {        /* insure space for new data */
  77.             /*
  78.              * Be careful about writing the last
  79.              * literal.  Must write up to that point
  80.              * and then copy the remainder to the
  81.              * front of the buffer.
  82.              */
  83.             if (state == LITERAL || state == LITERAL_RUN) {
  84.                 slop = op - lastliteral;
  85.                 tif->tif_rawcc += lastliteral - tif->tif_rawcp;
  86.                 if (!TIFFFlushData1(tif))
  87.                     return (-1);
  88.                 op = tif->tif_rawcp;
  89.                 for (; slop-- > 0; *op++ = *lastliteral++)
  90.                     ;
  91.                 lastliteral = tif->tif_rawcp;
  92.             } else {
  93.                 tif->tif_rawcc += op - tif->tif_rawcp;
  94.                 if (!TIFFFlushData1(tif))
  95.                     return (-1);
  96.                 op = tif->tif_rawcp;
  97.             }
  98.         }
  99.         switch (state) {
  100.         case BASE:        /* initial state, set run/literal */
  101.             if (n > 1) {
  102.                 state = RUN;
  103.                 if (n > 128) {
  104.                     *op++ = -127;
  105.                     *op++ = b;
  106.                     n -= 128;
  107.                     goto again;
  108.                 }
  109.                 *op++ = -(n-1);
  110.                 *op++ = b;
  111.             } else {
  112.                 lastliteral = op;
  113.                 *op++ = 0;
  114.                 *op++ = b;
  115.                 state = LITERAL;
  116.             }
  117.             break;
  118.         case LITERAL:        /* last object was literal string */
  119.             if (n > 1) {
  120.                 state = LITERAL_RUN;
  121.                 if (n > 128) {
  122.                     *op++ = -127;
  123.                     *op++ = b;
  124.                     n -= 128;
  125.                     goto again;
  126.                 }
  127.                 *op++ = -(n-1);        /* encode run */
  128.                 *op++ = b;
  129.             } else {            /* extend literal */
  130.                 if (++(*lastliteral) == 127)
  131.                     state = BASE;
  132.                 *op++ = b;
  133.             }
  134.             break;
  135.         case RUN:        /* last object was run */
  136.             if (n > 1) {
  137.                 if (n > 128) {
  138.                     *op++ = -127;
  139.                     *op++ = b;
  140.                     n -= 128;
  141.                     goto again;
  142.                 }
  143.                 *op++ = -(n-1);
  144.                 *op++ = b;
  145.             } else {
  146.                 lastliteral = op;
  147.                 *op++ = 0;
  148.                 *op++ = b;
  149.                 state = LITERAL;
  150.             }
  151.             break;
  152.         case LITERAL_RUN:    /* literal followed by a run */
  153.             /*
  154.              * Check to see if previous run should
  155.              * be converted to a literal, in which
  156.              * case we convert literal-run-literal
  157.              * to a single literal.
  158.              */
  159.             if (n == 1 && op[-2] == (char)-1 &&
  160.                 *lastliteral < 126) {
  161.                 state = (((*lastliteral) += 2) == 127 ?
  162.                     BASE : LITERAL);
  163.                 op[-2] = op[-1];    /* replicate */
  164.             } else
  165.                 state = RUN;
  166.             goto again;
  167.         }
  168.     }
  169.     tif->tif_rawcc += op - tif->tif_rawcp;
  170.     tif->tif_rawcp = op;
  171.     return (1);
  172. }
  173.  
  174. /*
  175.  * Encode a rectangular chunk of pixels.  We break it up
  176.  * into row-sized pieces to insure that encoded runs do
  177.  * not span rows.  Otherwise, there can be problems with
  178.  * the decoder if data is read, for example, by scanlines
  179.  * when it was encoded by strips.
  180.  */
  181. static int
  182. DECLARE4(PackBitsEncodeChunk, TIFF*, tif, u_char*, bp, u_long, cc, u_int, s)
  183. {
  184.     u_long rowsize = (u_long) tif->tif_data;
  185.  
  186.     assert(rowsize > 0);
  187.     while ((long)cc > 0) {
  188.         if (PackBitsEncode(tif, bp, rowsize, s) < 0)
  189.             return (-1);
  190.         bp += rowsize;
  191.         cc -= rowsize;
  192.     }
  193.     return (1);
  194. }
  195.  
  196. static int
  197. DECLARE4(PackBitsDecode, TIFF*, tif, register u_char*, op, register u_long, occ, u_int, s)
  198. {
  199.     register char *bp;
  200.     register int n, b;
  201.     register int cc;
  202.  
  203.     bp = tif->tif_rawcp; cc = tif->tif_rawcc;
  204.     while (cc > 0 && (long)occ > 0) {
  205.         n = (int) *bp++;
  206.         /*
  207.          * Watch out for compilers that
  208.          * don't sign extend chars...
  209.          */
  210.         if (n >= 128)
  211.             n -= 256;
  212.         if (n < 0) {        /* replicate next byte -n+1 times */
  213.             cc--;
  214.             if (n == -128)    /* nop */
  215.                 continue;
  216.             n = -n + 1;
  217.             occ -= n;
  218.             for (b = *bp++; n-- > 0;)
  219.                 *op++ = b;
  220.         } else {        /* copy next n+1 bytes literally */
  221.             memcpy(op, bp, ++n);
  222.             op += n; occ -= n;
  223.             bp += n; cc -= n;
  224.         }
  225.     }
  226.     tif->tif_rawcp = bp;
  227.     tif->tif_rawcc = cc;
  228.     if (occ > 0) {
  229.         TIFFError(tif->tif_name,
  230.             "PackBitsDecode: Not enough data for scanline %d",
  231.             tif->tif_row);
  232.         return (0);
  233.     }
  234.     /* check for buffer overruns? */
  235.     return (1);
  236. }
  237.  
  238. int
  239. DECLARE1(TIFFInitPackBits, TIFF*, tif)
  240. {
  241.     tif->tif_decoderow = PackBitsDecode;
  242.     tif->tif_decodestrip = PackBitsDecode;
  243.     tif->tif_decodetile = PackBitsDecode;
  244.     tif->tif_preencode = PackBitsPreEncode;
  245.     tif->tif_encoderow = PackBitsEncode;
  246.     tif->tif_encodestrip = PackBitsEncodeChunk;
  247.     tif->tif_encodetile = PackBitsEncodeChunk;
  248.     return (1);
  249. }
  250.